package utwente.sem.eindopdracht;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * De Tui is de Textuele UI klasse. Via de Tui wordt alle informatie naar de gebruiker van het
 * systeem gebracht. De Tui is de View van het MVC model in het systeem.
 * 
 * @author Richard Heijblom & Mark Wienk
 *
 */
public class Tui {
	private static Tui tui; //Singleton
	private static Controller controller;

	/**
	 * De Tui is de Textuele UI klasse. Via de Tui wordt alle informatie naar de gebruiker van het
	 * systeem gebracht. De Tui is de View van het MVC model in het systeem.
	 */
	private Tui() {
		toonBericht("Use Case Industries - v1");
		controller = Controller.getController();
	}
	
	/**
	 * Singleton voor Tui klasse
	 * @return Tui singelton
	 */
	public static Tui getUI() {
		if(Tui.tui == null) {
			tui = new Tui();
		}
		return tui;
	}
  
	/**
	 * Bij het openene van de applicatie dient het hoofdmenu getoond te worden.
	 */
	public void run() {
		controller.showHoofdmenu();
	}
  
	/**
	 * UI Implementatie voor de weergave van een bericht aan de gebruiker.
     * @param bericht
     */
	public void toonBericht(String bericht){
		System.out.println(bericht);
	}
  
  
	/**
     * UI Implementatie voor de weergave van een keuzemenu aan de gebruiker.
     * @param bericht Het begeleidende bericht bij het menu.
     * @param keuzeOpties De opties in het menu (de toString() van het Object wordt gebruikt voor de weergave).
     */
	public int toonMenu(String bericht, Object[] keuzeOpties) {
		toonLijst(bericht,keuzeOpties);
		return getNumeriekeInvoer(0,keuzeOpties.length -1);
	}
	
	/**
	 * Geeft alle items in een array van Objecten weer (via de toString van het object).
	 * @param bericht - Inleidend bericht.
	 * @param items - De objecten die weergegeven dienen te worden (weergegeven via de toString() methode).
	 */
	public void toonLijst(String bericht, Object[] items) {
		for(int i = 0; i < items.length; i++) {
			bericht = bericht.concat("\n\t" + i + " - " + items[i].toString());
		}
		toonBericht(bericht);
	}
	
	/**
	 * Vraag een numerieke Integer waarde aan de gebruiker zonder minimum en maximum waardes.
	 * @return een keuze van de gebruiker (int)
	 */
	public int getNumeriekeInvoer() {
		return getNumeriekeInvoer(Integer.MIN_VALUE, Integer.MAX_VALUE);
	}
	
	/**
	 * Verkrijg een numerieke invoer van de gebruiker met een minimum en maximum waarde
	 * @param min De minimumwaarde
	 * @param max De maximumwaarde
	 * @return de gecontroleerde invoer van de gebruiker.
	 */
	public int getNumeriekeInvoer(int min, int max) {
		int result;
		InputStreamReader line = new InputStreamReader(System.in);
		BufferedReader input   = new BufferedReader(line);
		
		//Bekijk of de waarde een Numerieke waarde is
		try {
			result = Integer.parseInt(input.readLine().trim());
		} catch (NumberFormatException e) {
			toonBericht("Kies een nummer uit het menu");
			result = getNumeriekeInvoer(min,max);
		} catch (IOException e) {
			toonBericht("Onbekende invoer, voer het nummer opnieuw in.");
			result = getNumeriekeInvoer(min,max);
		}
		
		//Bekijk of de waarde in de gespecificeerde range past
		if(result >= min && result <= max) {
			return result;
		} else {
			toonBericht("U hebt een verkeerd nummer ingevoerd, het nummer dient tussen " + min + " en " + max + "te liggen");
			return getNumeriekeInvoer(min,max);
		}
	}
	
	/**
	 * Verkrijg een tekst invoer van de gebruiker.
	 * @return Gecheckte invoer van de gebruiker (als String).
	 */
	public String getTekstInvoer() {
		String result;
		InputStreamReader line = new InputStreamReader(System.in);
		BufferedReader input   = new BufferedReader(line);
		
		try {
			result = input.readLine().trim();
		} catch (IOException e) {
			toonBericht("Onbekende invoer, voer de tekst opnieuw in.");
			result = getTekstInvoer();
		}
		return result;
	}
	
	/**
	 * Start de applicatie
	 * @param args
	 */
	public static void main(String[] args){
		getUI().run();
	}
}